package com.mhc.suzuki.service.impl;

import com.mhc.fiat.api.ProcessServiceWraper;
import com.mhc.fiat.api.message.ProcessMessage;
import com.mhc.haval.api.dto.StaffDTO;
import com.mhc.haval.api.service.IStaffRoleService;
import com.mhc.haval.security.model.User;
import com.mhc.suzuki.bo.SubmitTaskBO;
import com.mhc.suzuki.constant.*;
import com.mhc.suzuki.dal.model.OrderAuditApplyDO;
import com.mhc.suzuki.dal.model.OrderAuditTaskDO;
import com.mhc.suzuki.dal.model.OrderDO;
import com.mhc.suzuki.dal.model.PaymentRequestDO;
import com.mhc.suzuki.dal.query.OrderAuditApplyQuery;
import com.mhc.suzuki.dal.query.OrderAuditTaskQuery;
import com.mhc.suzuki.dal.query.OrderQuery;
import com.mhc.suzuki.dal.query.PaymentRequestQuery;
import com.mhc.suzuki.exception.SuzukiCommonException;
import com.mhc.suzuki.manager.OrderAuditApplyManager;
import com.mhc.suzuki.manager.OrderAuditTaskManager;
import com.mhc.suzuki.manager.OrderManager;
import com.mhc.suzuki.manager.PaymentRequestManager;
import com.mhc.suzuki.service.MessageService;
import com.mhc.suzuki.service.OrderAuditTaskService;
import com.mhc.suzuki.service.PaymentNotificationService;
import com.mhc.suzuki.util.BeanCopierUtil;
import com.mhc.suzuki.util.Constant;
import com.mhc.suzuki.vo.OrderAuditTaskVO;
import com.subaru.common.entity.BizResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.util.*;

/**
 * Created by HMJ on 2017/8/24.
 */
@Slf4j
@Service
@Transactional(rollbackFor = Exception.class)
public class OrderAuditTaskServiceImpl implements OrderAuditTaskService {

    @Autowired
    private OrderAuditTaskManager orderAuditTaskManager;

    @Autowired
    private IStaffRoleService staffRoleService;

    @Autowired
    private MessageService messageService;

    @Autowired
    private OrderManager orderManager;

    @Autowired
    private OrderAuditApplyManager orderAuditApplyManager;

//    @Autowired
//    private ProcessServiceWraper processServiceWraper;

    @Autowired
    private PaymentRequestManager paymentRequestManager;

    @Autowired
    private PaymentNotificationService paymentNotificationService;

    @Override
    public List<OrderAuditTaskVO> queryOrderAuditTaskList(String orderNO, Integer bizType, Integer approvalResult, Long applyId,String roleCode) {
        OrderAuditTaskQuery orderAuditTaskQuery = new OrderAuditTaskQuery();
        OrderAuditTaskQuery.Criteria criteria = orderAuditTaskQuery.createCriteria();
        criteria.andOrderNoEqualTo(orderNO).andApplyTypeEqualTo(bizType);
        if (approvalResult != null) {
            criteria.andApprovalResultEqualTo(approvalResult);
        }
        if (applyId != null) {
            criteria.andApplyIdEqualTo(applyId);
        }
        List<OrderAuditTaskVO> auditTaskVOList = new ArrayList<>();
        List<OrderAuditTaskDO> orderAuditTaskDOList = orderAuditTaskManager.selectByQuery(orderAuditTaskQuery);
        orderAuditTaskDOList.forEach(orderAuditTaskDO -> {
            if(!RoleTypeEnum.ROLE_SPSALESMAN.getCode().equals(roleCode)){
                orderAuditTaskDO.setCustomerAnalysis(orderAuditTaskDO.getCustomerAnalysis());
            }else{
                orderAuditTaskDO.setCustomerAnalysis("");
            }
            OrderAuditTaskVO orderAuditTaskVO = BeanCopierUtil.convert(orderAuditTaskDO, OrderAuditTaskVO.class);
            orderAuditTaskVO.setApprovalResult(ApprovalResultEnum.getNameByCode(orderAuditTaskDO.getApprovalResult()));
            auditTaskVOList.add(orderAuditTaskVO);
        });
        return auditTaskVOList;
    }

    @Override
    public List<OrderAuditTaskVO> queryOrderAuditTaskList(String orderNO, Integer bizType, Integer approvalResult) {
      return this.queryOrderAuditTaskList(orderNO, bizType, approvalResult, null, null);
    }

    @Override
    public List<OrderAuditTaskVO> queryOrderAuditTaskList(String orderNO, Integer bizType) {
        return this.queryOrderAuditTaskList(orderNO, bizType, null);
    }

    /**
     * 生成待办任务
     * @param processMessage
     * @param msg
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void createAuditTask(ProcessMessage processMessage,Map<String, Object> msg) throws Exception{
        /**执行消息成功后，获取消息内容创建新待办任务**/
        /**新增待办任务数据**/
        log.info("正在生成待办任务数据...");
        OrderAuditTaskDO orderAuditTaskRecord = new OrderAuditTaskDO();
        orderAuditTaskRecord.setApplyId(Long.parseLong(msg.get("applyId").toString()));           //申请ID
        orderAuditTaskRecord.setNodeName(processMessage.getTaskDefName());
        orderAuditTaskRecord.setFlowNodeId(processMessage.getTaskId());                           //节点任务ID
        orderAuditTaskRecord.setOrderNo(processMessage.getBusinessKey());                         //订单号
        orderAuditTaskRecord.setApproveStaffId(Long.parseLong(processMessage.getAssignee()));     //审批人员工编号
        /**调用外部接口查询审核人员姓名**/
        StaffDTO staffDTO = staffRoleService.selectByStaffName(Long.parseLong(processMessage.getAssignee()));
        orderAuditTaskRecord.setApproveStaffName(staffDTO.getStaffName());  //审核人员的名称
        orderAuditTaskRecord.setApplyType(Integer.parseInt(msg.get("applyType").toString()));         //申请类型
        orderAuditTaskRecord.setTaskStatus(TaskStatusEnum.PENDING.getCode());        //任务状态
        orderAuditTaskManager.insertSelective(orderAuditTaskRecord);
        log.info("生成待办任务数据完成...");
        log.info("开始生成消息提醒...");
        try {
            sendMessage(orderAuditTaskRecord, processMessage);
        } catch (Exception e){
            log.error(e.getMessage(), e);
        }
        log.info("消息提醒成功...");
    }

    /**
     * 流程结束后处理数据
     * @param msg
     * @throws SuzukiCommonException
     */
    public void getAuditTaskList(Map<String, Object> msg) throws SuzukiCommonException{
        OrderQuery orderQuery = new OrderQuery();
        OrderDO orderRecord = new OrderDO();
        /**获取订单编号**/
        String orderNo = msg.get("orderId").toString();
        /**获取流程申请类型**/
        int applyType = Integer.parseInt(msg.get("applyType").toString());  //流程申请类型
        log.info("当前申请类型为{}...", ApplyTypeEnum.getApplyTypeEnum(applyType).getName());
        if(applyType == ApplyTypeEnum.LOAN_APPLY.getCode() || applyType == ApplyTypeEnum.ACCOM_APPLY.getCode()){
            /**贷款、通融申请审核通过,需要把订单状态置为贷款申请通过**/
            orderRecord.setOrderStatus(OrderStatusEnum.APPLICATION_IS_APPROVED.getCode());   //贷款申请通过
        }
        if(applyType == ApplyTypeEnum.MODIFY_APPLY.getCode()){
            /**修改申请审核通过,需要判断订单申请之前的状态**/
            Boolean advancePaymentFlag = paymentNotificationService.isOrderStatuByPayment(orderNo);
            if (advancePaymentFlag) {
                log.info("当前订单在发起申请前属于垫款后...");
                orderRecord.setOrderStatus(OrderStatusEnum.ALREADY_PAYMENT.getCode());
            } else {
                log.info("当前订单在发起申请前属于垫款前...");
                orderRecord.setOrderStatus(OrderStatusEnum.APPLICATION_IS_APPROVED.getCode());
            }
        }
        if(applyType == ApplyTypeEnum.PAYMENT_REQUEST_APPLY.getCode()){
            /**打款申请审核通过,把垫款信息设置为已打款**/
            PaymentRequestDO paymentRequestRecord = new PaymentRequestDO();
            PaymentRequestQuery paymentRequestQuery = new PaymentRequestQuery();
            paymentRequestRecord.setApplyStatus(PaymentRequestStatusEnum.PAID.getCode());
            paymentRequestQuery.createCriteria().andOrderNoEqualTo(orderNo);
            paymentRequestManager.updateByQuerySelective(paymentRequestRecord,paymentRequestQuery);
            /**打款申请审核通过,需要把订单状态置为财务已垫款**/
            orderRecord.setOrderStatus(OrderStatusEnum.ALREADY_PAYMENT.getCode());   //财务已垫款
        }
        log.info("正在修改订单状态...");
        log.info("状态为:{}", OrderStatusEnum.getOrderStatusEnum(orderRecord.getOrderStatus()));
        orderQuery.createCriteria().andOrderNoEqualTo(orderNo);    //订单号
        orderManager.updateByQuerySelective(orderRecord,orderQuery);
        log.info("修改完成...");
        /**修改申请表数据，将当前申请置为已删除**/
        log.info("正在将完成的申请数据更改状态");
        OrderAuditApplyDO record = new OrderAuditApplyDO();
        OrderAuditApplyQuery query = new OrderAuditApplyQuery();
        record.setApplyStatus(ApplyStatusEnum.COMPLETE.getCode());    //设置为已完成
        query.createCriteria().andOrderNoEqualTo(orderNo).andApplyIdEqualTo(Long.parseLong(msg.get("applyId").toString()));
        orderAuditApplyManager.updateByQuerySelective(record, query);
        log.info("更改完成");
    }


    /**
     * 查询订单是否存在相同的申请
     * @param submitTaskBO
     * @return
     * @throws Exception
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean closedTask(SubmitTaskBO submitTaskBO, User logedUser,int applyStatus) throws SuzukiCommonException {
        /**根据订单号查询该订单下是否存在有效的申请**/
        OrderAuditApplyQuery orderAuditApplyQuery = new OrderAuditApplyQuery();
        String orderNo = submitTaskBO.getOrderNo();     //获取订单号
        log.info("查询订单：{}下是否存在正常的申请...", orderNo);
        orderAuditApplyQuery.createCriteria().andOrderNoEqualTo(orderNo).andApplyStatusEqualTo(ApplyStatusEnum.NORMAL.getCode());   //查询正常的状态
        List<OrderAuditApplyDO> orderAuditApplyList = orderAuditApplyManager.selectByQuery(orderAuditApplyQuery);
        if(CollectionUtils.isEmpty(orderAuditApplyList)) {
            return Boolean.TRUE;
        }
        /**存在有效的申请，检查本次申请是否与存在的申请一致，如果一致，则不关闭；如果不一致，则不关闭**/
        log.info("存在正常的申请...");
        if(orderAuditApplyList.get(0).getApplyType().equals(submitTaskBO.getApplyType())){
            log.info("申请类型相同...");
            return Boolean.FALSE;
        }else {
            log.info("申请类型不同...");
            log.info("业务员：{},开始废除订单号为{}的所有申请...", logedUser.getStaffName(), orderNo);
            log.info("正在关闭流程组件...");
            /**1、停止工作流**/
            try {
//                BizResult<Boolean> cancelResult = processServiceWraper.cancelProcess(orderAuditApplyList.get(0).getFlowInstanceId());
                BizResult<Boolean> cancelResult = new BizResult<>();
                if (Boolean.TRUE.equals(cancelResult.getData())) {
                    log.info("关闭流程组件成功...");
                    /**2、删除数据**/
                    log.info("正在重置待办任务列表");
                    OrderAuditApplyDO record = new OrderAuditApplyDO();
                    OrderAuditApplyQuery query = new OrderAuditApplyQuery();
                    record.setApplyStatus(applyStatus);
                    query.createCriteria().andOrderNoEqualTo(orderNo);
                    orderAuditApplyManager.updateByQuerySelective(record, query);
                    log.info("重置完成...");
                }
                return Boolean.TRUE;
            } catch (Exception e){
                if(("org.activiti.engine.ActivitiObjectNotFoundException").equals(e.getMessage().substring(0,e.getMessage().indexOf(":")))){
                    log.info("流程实例已被关闭...");
                    return Boolean.TRUE;
                }else {
                    //关闭流程组件失败，工作流关闭异常
                    throw new SuzukiCommonException(ErrorCodeEnum.CANCEL_PROCESS);
                }
            }
        }
    }




    /**
     * 审核通过时的消息发送
     * @param orderAuditTaskRecord
     * @param processMessage
     * @throws SuzukiCommonException
     * @throws IOException
     */
    private void sendMessage(OrderAuditTaskDO orderAuditTaskRecord, ProcessMessage processMessage) throws SuzukiCommonException, IOException{

        /**判断是否为审核不通过的状态**/
        Integer applyType = orderAuditTaskRecord.getApplyType();
        Boolean isNoPass = false;
        //是否为通融过件审核不通过
        Boolean isAccom = false;
        Set<String> queryKeys = new HashSet<>();
        queryKeys.add(Constant.SALEMANAGERAPPROVED);
        queryKeys.add(Constant.AUDITORAPPROVED);
        queryKeys.add(Constant.AUDITORMANAGERAPPROVED);
        queryKeys.add(Constant.RISKLEADERAPPROVED);
        queryKeys.add(Constant.SALEMANMODIFIEDAPPLY);
        queryKeys.add(Constant.COOPERATIVEAPPROVED);
        queryKeys.add(Constant.RISKCONTROLAPPROVED);
        queryKeys.add(Constant.ISGPSINSTALLED);
        queryKeys.add(Constant.ISFILECORRECT);
        Map<String, Object> results = processMessage.getProcessVariables();

        for (Map.Entry<String, Object> entry : results.entrySet()){

            String s = entry.getKey();
            //通融审核中审核经理不同意
            if (queryKeys.contains(s)
                    && "auditorManagerApproved".equals(s)
                    && Integer.parseInt((String) results.get(s)) == 3
                    && ApplyTypeEnum.ACCOM_APPLY.getCode().equals(applyType)){
                isAccom = true;
            }

            //通融审核中分管领导不同意
            if (queryKeys.contains(s)
                    && "riskLeaderApproved".equals(s)
                    && Integer.parseInt((String) results.get(s)) == 0
                    && ApplyTypeEnum.ACCOM_APPLY.getCode().equals(applyType)){
                isAccom = true;
            }

            if (queryKeys.contains(s) && Integer.parseInt((String) results.get(s)) == 0){
                isNoPass = true;
            }
        }

        log.info("isNoPass:" + isNoPass + "isAccom:" + isAccom);
        if (isAccom){//此情况下发送待办任务
            log.info("通融审核中的不同意");
            messageService.sendMessage(processMessage, orderAuditTaskRecord.getApplyType());
        } else {
            if(!isNoPass){//订单状态未改变, 或原始订单状态为征信已录入，审核通过等,发送待办任务消息
                log.info("审核通过，发送消息之下一个审核人员");
                messageService.sendMessage(processMessage, orderAuditTaskRecord.getApplyType());
            }
        }
    }

}
